/** 
Copyright (c) 2010, Sheikh Abdul Wahid Ahmed
Details @ http://extremecodeworld.codeplex.com/license
**/

using System;
using EXtremecode.Utils;
using System.Data;
using System.Collections;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using EXtremecode.DataAccessLayer.Services;
namespace EXtremecode.DataAccessLayer
{
	/// <summary>
	/// Summary description for Service.
	/// </summary>
	
		
	public class ServiceConnection:IDbConnection		 
	{

        private ServiceDataAccessor accessor;
        public ServiceConnection(ServiceDataAccessor accessor)
        {
            this.accessor = accessor;
        }

 	
        #region IDbConnection Members

		public void ChangeDatabase(string databaseName)
		{
		}

		public IDbTransaction BeginTransaction(IsolationLevel il)
		{
			return null;
		}

		IDbTransaction System.Data.IDbConnection.BeginTransaction()
		{
			return null;
		}


        private ConnectionState state = ConnectionState.Closed;
        public ConnectionState State
		{
			get
			{
				return state;
			}
		}

		public string ConnectionString
		{
			get
			{
				return string.Empty;
			}
			set
			{
                   
			}
		}

		public IDbCommand CreateCommand()
		{
		    IDbCommand cmd = new ServiceCommand(accessor);
            cmd.Connection = this;
            return cmd;
		}

		public void Open()
		{

            state = ConnectionState.Open;
		}


		public void Close()
		{
            
            state = ConnectionState.Closed;
		}

        public string Database
        {
            get
            {
                return null;
            }
        }

		public int ConnectionTimeout
		{
			get
			{
				return 0;
			}
		}

		#endregion

		#region IDisposable Members

		public void Dispose()
		{
		}

		#endregion
	}
    [DataContract] 
    public class ServiceDataReader:IDataReader
	{
        public ServiceDataReader(List<object[]> data)
        {
            this.data = data;
        }

        public ServiceDataReader()
        {
        }

        [DataMember]
        public Dictionary<string, int> fieldIndexes = new Dictionary<string, int>();

        [DataMember]
        public List<object[]> data = new List<object[]>();

        

        private int currentRowIndex = -1;
        private bool hasReadingStarted = false;

        
        public void AddFieldIndex(string filedName, int index)
        {
            if (!fieldIndexes.ContainsKey(filedName.ToLower()))
            {
                fieldIndexes.Add(filedName.ToLower(), index);
            }
        }

		#region IDataReader Members

		public int RecordsAffected
		{
			get
			{
                return data.Count;
			}
		}

		public bool IsClosed
		{
			get
			{
				return false;
			}
		}

		public bool NextResult()
		{
			// TODO:  Add ServiceDataReader.NextResult implementation
			return false;
		}

		public void Close()
		{
			// TODO:  Add ServiceDataReader.Close implementation
		}

		public bool Read()
		{
            if (!hasReadingStarted)
            {
                currentRowIndex = -1;
                hasReadingStarted = true;
            }
            currentRowIndex++;

            if (currentRowIndex < data.Count)
            {
                return true;
            }
            else
            {
                hasReadingStarted = false;
                return false;
            }

		}

		public int Depth
		{
			get
			{
				// TODO:  Add ServiceDataReader.Depth getter implementation
				return 0;
			}
		}

		public DataTable GetSchemaTable()
		{
			// TODO:  Add ServiceDataReader.GetSchemaTable implementation
			return null;
		}

		#endregion

		#region IDisposable Members

		public void Dispose()
		{
			// TODO:  Add ServiceDataReader.Dispose implementation
		}

		#endregion

		#region IDataRecord Members

		public int GetInt32(int i)
		{
			// TODO:  Add ServiceDataReader.GetInt32 implementation
			return 0;
		}

		public object this[string name]
		{
			get
			{
                if (fieldIndexes.ContainsKey(name.ToLower()))
                {
                    return data[currentRowIndex][fieldIndexes[name.ToLower()]];
                }
                else
                {
                    return null;
                }
			}
		}

		object System.Data.IDataRecord.this[int i]
		{
			get
			{
                return data[currentRowIndex][i];
			}
		}

		public object GetValue(int i)
		{
			// TODO:  Add ServiceDataReader.GetValue implementation
			return null;
		}

		public bool IsDBNull(int i)
		{
			// TODO:  Add ServiceDataReader.IsDBNull implementation
			return false;
		}

		public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
		{
			// TODO:  Add ServiceDataReader.GetBytes implementation
			return 0;
		}

		public byte GetByte(int i)
		{
			// TODO:  Add ServiceDataReader.GetByte implementation
			return 0;
		}

		public Type GetFieldType(int i)
		{
			// TODO:  Add ServiceDataReader.GetFieldType implementation
			return null;
		}

		public decimal GetDecimal(int i)
		{
			// TODO:  Add ServiceDataReader.GetDecimal implementation
			return 0;
		}

		public int GetValues(object[] values)
		{
			// TODO:  Add ServiceDataReader.GetValues implementation
			return 0;
		}

		public string GetName(int i)
		{
			// TODO:  Add ServiceDataReader.GetName implementation
			return null;
		}

		public int FieldCount
		{
			get
			{
				// TODO:  Add ServiceDataReader.FieldCount getter implementation
				return 0;
			}
		}

		public long GetInt64(int i)
		{
			// TODO:  Add ServiceDataReader.GetInt64 implementation
			return 0;
		}

		public double GetDouble(int i)
		{
			// TODO:  Add ServiceDataReader.GetDouble implementation
			return 0;
		}

		public bool GetBoolean(int i)
		{
			// TODO:  Add ServiceDataReader.GetBoolean implementation
			return false;
		}

		public Guid GetGuid(int i)
		{
			// TODO:  Add ServiceDataReader.GetGuid implementation
			return new Guid ();
		}

		public DateTime GetDateTime(int i)
		{
			// TODO:  Add ServiceDataReader.GetDateTime implementation
			return new DateTime ();
		}

		public int GetOrdinal(string name)
		{
			// TODO:  Add ServiceDataReader.GetOrdinal implementation
			return 0;
		}

		public string GetDataTypeName(int i)
		{
			// TODO:  Add ServiceDataReader.GetDataTypeName implementation
			return null;
		}

		public float GetFloat(int i)
		{
			// TODO:  Add ServiceDataReader.GetFloat implementation
			return 0;
		}

		public IDataReader GetData(int i)
		{
			// TODO:  Add ServiceDataReader.GetData implementation
			return null;
		}

		public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
		{
			// TODO:  Add ServiceDataReader.GetChars implementation
			return 0;
		}

		public string GetString(int i)
		{
			// TODO:  Add ServiceDataReader.GetString implementation
			return null;
		}

		public char GetChar(int i)
		{
			// TODO:  Add ServiceDataReader.GetChar implementation
			return '\0';
		}

		public short GetInt16(int i)
		{
			// TODO:  Add ServiceDataReader.GetInt16 implementation
			return 0;
		}

		#endregion
    }


    [DataContract(
   Namespace = "http://microsoft.wcf.documentation",
   Name = "ServiceCommand")] 
    public class ServiceCommand:IDbCommand
	{

        private ServiceDataAccessor accessor;

        public ServiceDataAccessor Accessor
        {
            get { return accessor; }
        }
        public ServiceCommand(ServiceDataAccessor accessor)
        {
            this.accessor = accessor;
        }

        public ServiceCommand()
        {
        }

        #region IDbCommand Members

        private void ValidateConnection()
        {
            if (connection == null)
            {
                throw new Exception("[UC] no conection attached with command");
            }
            else if (connection.State == ConnectionState.Closed)
            {
                throw new Exception(
                    string.Format("[UC] conection [{0}] closed",
                    connection.Database));
            }
        }
        public void Cancel()
		{
		}

		public void Prepare()
		{
        }

        public IDataReader ExecuteReader(CommandBehavior behavior)
        {
            ValidateConnection();
            ServiceDataReader reader = accessor.ServiceClient.ExecuteReader(this,
                accessor.MappedAccessorName,
                false);
            
            return reader;
            
        }

        IDataReader System.Data.IDbCommand.ExecuteReader()
        {
            return  ExecuteReader(CommandBehavior.Default);
        }

        public object ExecuteScalar()
        {
            IDataReader reader = ExecuteReader(CommandBehavior.Default);
            if (reader.RecordsAffected > 0)
            {
                return reader[0];
            }
            else
            {
                return null;
            }
        }

        public int ExecuteNonQuery()
        {
            ValidateConnection();
            return accessor.ServiceClient.ExecuteNonQuery(this,
                accessor.MappedAccessorName,
                false);
            
        }

        public IDbDataParameter CreateParameter()
        {
            return new ServiceParameter();
        }


        private CommandType commandType = CommandType.Text;

        [DataMember] 
        public CommandType CommandType
		{
			get
			{
				return commandType;
			}
			set
			{
                commandType = value;
			}
		}


        private int commandTimeout;
        
        [DataMember] 
		public int CommandTimeout
		{
			get
			{
				return commandTimeout ;
			}
			set
			{
                commandTimeout = value;
			}
		}



        private ServiceConnection connection;

        public IDbConnection Connection
		{
			get
			{
				return connection;
			}
			set
			{
                connection = (ServiceConnection)value;
			}
		}

        
        
        private UpdateRowSource updatedRowSource = UpdateRowSource.Both;

        [DataMember]
        public UpdateRowSource UpdatedRowSource
		{
			get
			{
				return updatedRowSource;
			}
			set
			{
                updatedRowSource = value;
			}
		}

        private string commandText = string.Empty;

        [DataMember] 
        public string CommandText
		{
			get
			{
				return commandText;
			}
			set
			{
                commandText = value;
			}
		}


        private IDataParameterCollection paramCollection = new ServiceParameterCollection();
        
        [DataMember] 
        public IDataParameterCollection Parameters
		{
			get
			{
				return paramCollection;
			}
            set
            {
                paramCollection = value;
            }
		}

		//transction is not implemented
        public IDbTransaction Transaction
		{
			get
			{
				return null;
			}
			set
			{
			}
		}

		#endregion

		#region IDisposable Members

		public void Dispose()
		{
		}

		#endregion
	}

	[DataContract] 
    public class ServiceParameter:IDbDataParameter
	{
        public ServiceParameter(string name, DbType dbType)
        {
            parameterName = name;
            this.dbType = dbType;
        }

        public ServiceParameter()
        {
        }
		
        #region IDataParameter Members

        
        private ParameterDirection direction = ParameterDirection.Input;

        [DataMember]
        public ParameterDirection Direction
		{
			get
			{
				return direction;
			}
			set
			{
                direction = value;
			}
		}

        
        
        private DbType dbType = DbType.String;

        [DataMember]
        public DbType DbType
		{
			get
			{
                return dbType;
			}
			set
			{
                dbType = value;
			}
		}

        


        private object val = null;

        [DataMember]
        public object Value
		{
			get
			{
				return val;
			}
			set
			{
                val = value;
			}
		}


        


        private bool isNullable = false;

        [DataMember]
        public bool IsNullable
		{
			get
			{
				return isNullable;
			}
            set
            {
                isNullable = value;
            }
		}


        
        
        
        private DataRowVersion sourceVersion= DataRowVersion.Current;

        [DataMember]
        public DataRowVersion SourceVersion
		{
			get
			{
				return sourceVersion;
			}
			set
			{
                sourceVersion = value;
			}
		}

        


        private string parameterName = string.Empty;

        [DataMember]
        public string ParameterName
		{
			get
			{
				return parameterName;
			}
			set
			{
                parameterName = value;
			}
		}

        


        private string sourceColumn = string.Empty;

        [DataMember]
        public string SourceColumn
		{
			get
			{
				return sourceColumn;
			}
			set
			{
                sourceColumn = value;
			}
		}

		#endregion

        #region IDbDataParameter Members


        private byte precision;
        [DataMember]
        public byte Precision
        {
            get
            {
                return precision;
            }
            set
            {
                precision = value;
            }
        }



        private byte scale;
        [DataMember]
        public byte Scale
        {
            get
            {
                return scale;
            }
            set
            {
                scale = value;
            }
        }



        private int size;
        [DataMember]
        public int Size
        {
            get
            {
                return size;
            }
            set
            {
                size = value;
            }
        }
        

        #endregion
    }


    [DataContract]
    public class ServiceParameterCollection:IDataParameterCollection,IEnumerator 
	{
        [DataMember]
        public Dictionary<string, ServiceParameter> paramList = new Dictionary<string, ServiceParameter>(StringComparer.OrdinalIgnoreCase);

        [DataMember]
        public List<string> paramNames = new List<string>();
        
        #region IDataParameterCollection Members

        public void RemoveAt(string parameterName)
        {
            paramList.Remove(parameterName);
        }
        
        public object this[string parameterName]
		{
			get
			{     
                  return paramList[parameterName];
			}
			set
			{
                if (value.GetType() == typeof(ServiceParameter))
                {
                    paramList[parameterName] = (ServiceParameter)value;
                }
                else
                {
                    throw new Exception(
                        string.Format("only {0} objects allowed",
                        typeof(ServiceParameter)));
                }
                
               
			}
		}


		public bool Contains(string parameterName)
		{

            return paramList.ContainsKey(parameterName);
		}

		public int IndexOf(string parameterName)
		{
			return paramNames.IndexOf(parameterName);
		}

		#endregion

		#region IList Members

		public bool IsReadOnly
		{
			get
			{
				return false;
			}
		}

		object System.Collections.IList.this[int index]
		{
			get
			{
                string paramName = paramNames[index];
                return paramList[paramName];
			}
			set
			{
                if (value.GetType() == typeof(ServiceParameter))
                {
                    paramList[paramNames[index]] = (ServiceParameter)value;
                }
                else
                {
                    throw new Exception(
                        string.Format("only {0} objects allowed",
                        typeof(ServiceParameter)));
                }
			}
		}

		void System.Collections.IList.RemoveAt(int index)
		{
            string paramName =  paramNames[index];
            paramNames.RemoveAt(index);

            paramList.Remove(paramName);
        }

		public void Insert(int index, object value)
		{
            if (value.GetType() == typeof(ServiceParameter))
            {
                string paramName = ((ServiceParameter)value).ParameterName;
                paramList.Add(paramName, (ServiceParameter)value);
                paramNames.Insert(index, paramName);
            }
            else
            {
                throw new Exception(
                    string.Format("only {0} objects allowed",
                    typeof(ServiceParameter)));
            }
            
            
		}

		public void Remove(object value)
		{
            if (value.GetType() == typeof(ServiceParameter))
            {
                string paramName = ((ServiceParameter)value).ParameterName;
                paramList.Remove(paramName);
                paramNames.Remove(paramName);

            }
            else
            {
                throw new Exception(
                    string.Format("only {0} objects allowed",
                    typeof(ServiceParameter)));
            }
		}

		bool System.Collections.IList.Contains(object value)
		{
			return paramList.ContainsValue((ServiceParameter)value);
		}

		public void Clear()
		{
            paramList.Clear();
            paramNames.Clear();
		}

		int System.Collections.IList.IndexOf(object value)
		{
            if (value.GetType() == typeof(ServiceParameter))
            {
                string paramName = ((ServiceParameter)value).ParameterName;
                return paramNames.IndexOf(paramName);
            }
            else
            {
                throw new Exception(
                    string.Format("only {0} objects allowed",
                    typeof(ServiceParameter)));
            }
		}

		public int Add(object value)
		{
            if (value.GetType() == typeof(ServiceParameter))
            {
                ServiceParameter param = (ServiceParameter)value;
                paramList.Add(param.ParameterName, param);
                paramNames.Add(param.ParameterName); 
                return 1;
            }
            else
            {
                throw new Exception(
                    string.Format("only {0} objects allowed",
                    typeof(ServiceParameter)));
            }
            
            
		}

		public bool IsFixedSize
		{
			get
			{
				return false;
			}
		}

		#endregion

		#region ICollection Members

		public bool IsSynchronized
		{
			get
			{
				return false;
			}
		}

		public int Count
		{
			get
			{
				return paramList.Count;
			}
		}

		public void CopyTo(Array array, int index)
		{
            
		}

		public object SyncRoot
		{
			get
			{
				return null;
			}
		}

		#endregion

		#region IEnumerable Members

		public System.Collections.IEnumerator GetEnumerator()
        {
            Reset();
            return this;
		}

		#endregion
	
		#region IEnumerator Members

		private int currentIndex = -1;
        public void Reset()
		{
            currentIndex = -1;
		}

		public object Current
		{
			get
			{
                string parameterName = paramNames[currentIndex];
                return paramList[parameterName];
			}
		}

		public bool MoveNext()
		{
            return (paramList.Count > ++currentIndex);
		}

		#endregion

        
    }
    [DataContract]
    public class ServiceDataAdapter:IDbDataAdapter
	{
        private ServiceDataAccessor accessor;
        public ServiceDataAdapter(ServiceDataAccessor accessor)
        {
            this.accessor = accessor;
        }

        #region IDbDataAdapter Members


        public IDbCommand updateCommand;

        [DataMember]
        public IDbCommand UpdateCommand
		{
			get
			{
                return updateCommand;
			}
			set
			{
                if (value == null)
                {
                    updateCommand = value;
                }
                else
                {
                    if (value.GetType() == typeof(ServiceCommand))
                    {
                        updateCommand = value;
                    }
                    else
                    {
                        throw new Exception(
                            string.Format("only {0} objects allowed",
                            typeof(ServiceCommand)));
                    }
                }
                
			}
		}

        private IDbCommand selectCommand;

        [DataMember]
        public IDbCommand SelectCommand
		{
            get
            {
                return selectCommand;
            }
            set
            {
                if (value == null)
                {
                    selectCommand = value;
                }
                else
                {
                    if (value.GetType() == typeof(ServiceCommand))
                    {
                        selectCommand = value;
                    }
                    else
                    {
                        throw new Exception(
                            string.Format("only {0} objects allowed",
                            typeof(ServiceCommand)));
                    }
                }

            }
		}


        private IDbCommand deleteCommand;

        [DataMember]
        public IDbCommand DeleteCommand
		{
            get
            {
                return deleteCommand;
            }
            set
            {
                if (value == null)
                {
                    deleteCommand = value;
                }
                else
                {
                    if (value.GetType() == typeof(ServiceCommand))
                    {
                        deleteCommand = value;
                    }
                    else
                    {
                        throw new Exception(
                            string.Format("only {0} objects allowed",
                            typeof(ServiceCommand)));
                    }
                }


            }
		}


        private IDbCommand insertCommand;

        [DataMember]
        public IDbCommand InsertCommand
		{
            get
            {
                return insertCommand;
            }
            set
            {
                if (value == null)
                {
                    insertCommand = value;
                }
                else
                {
                    if (value.GetType() == typeof(ServiceCommand))
                    {
                        insertCommand = value;
                    }
                    else
                    {
                        throw new Exception(
                            string.Format("only {0} objects allowed",
                            typeof(ServiceCommand)));
                    }
                }

            }
		}

		#endregion

		#region IDataAdapter Members

		public int Fill(DataSet dataSet)
		{
			
            DataSet filledDataSet = accessor.ServiceClient.Fill(this,dataSet, 
                accessor.MappedAccessorName,
                false);
            dataSet.Merge(filledDataSet);
            return dataSet.Tables["Table"].Rows.Count;
		}

		public ITableMappingCollection TableMappings
		{
			get
			{
				return null;
			}
		}


        private  MissingSchemaAction missingSchemaAction = MissingSchemaAction.Ignore;

        [DataMember]
        public MissingSchemaAction MissingSchemaAction
		{
			get
			{
                return missingSchemaAction;
			}
			set
			{
                missingSchemaAction = value;
			}
		}


        private MissingMappingAction missingMappingAction = MissingMappingAction.Passthrough;

        [DataMember]
        public MissingMappingAction MissingMappingAction
		{
			get
			{
				return missingMappingAction;
			}
			set
			{
                missingMappingAction = value;
			}
		}

		public IDataParameter[] GetFillParameters()
		{
			return null;
		}

		public DataTable[] FillSchema(DataSet dataSet, SchemaType schemaType)
		{
			return null;
		}

		public int Update(DataSet dataSet)
		{
            DataSet dsWithChangesOnly = dataSet.GetChanges();
            if (dsWithChangesOnly == null
                || !dsWithChangesOnly.Tables.Contains("Table")
                || dsWithChangesOnly.Tables["Table"].Rows.Count == 0)
            {
                return 0;
            }

            DataSet updatedDataSet = accessor.ServiceClient.Update(this, dsWithChangesOnly,
                accessor.MappedAccessorName,
                false);
            dataSet.Merge(updatedDataSet);
            return updatedDataSet.Tables["Table"].Rows.Count;
		}

		#endregion
	}
	
		

}
